<!-- 数据切割组件 -->
<script setup>
import { onMounted, ref, nextTick, onBeforeUnmount, computed } from 'vue';
import { useRoute } from 'vue-router';
import { UploadFilled } from '@element-plus/icons-vue';
import { ElButton, ElCascader, ElIcon, ElMessage, ElUpload } from 'element-plus';
import * as turf from '@turf/turf';
import 'mapbox-gl-compare/dist/mapbox-gl-compare.css';
import { BASE_GEOSERVER_URL } from '@/apis';
import { getRelationById } from '@/apis/api-map-server';
import { cuttingToShp } from '@/apis/api-map-server';
import BorderBoxBg from '@/components/BorderBoxBg.vue';
import { UPLOAD_FILE_TYPE_ZIP, downloadBinaryFile } from '@/utils/helper';
import { GET_MAPBOX_MAP } from '@/utils/map-utils';

const cascaderProps = {
  emitPath: false,
};
const route = useRoute();
const emit = defineEmits(['cuttingClose']);

const mapImgList = ref([]);
const layer = ref('');
const fileList = ref([]);
const loading = ref(false);
const layerList = computed(() => {
  return mapImgList.value.map((item) => item?.children || []).flat(1);
});
const targetData = ref();

const getRelationByIdApi = async () => {
  const [err, data] = await getRelationById({
    menuCode: route.query?.code,
  });

  if (!err) {
    mapImgList.value = data.map((item) => {
      return {
        ...item,
        label: item.serviceName,
        value: item.serviceName,
        children:
          item?.children?.map((el) => {
            let id = `${item.id}${Math.random()}`;

            return {
              ...el,
              fid: item.id,
              id,
              label: el.layerMeta.name,
              value: id,
              url: `${BASE_GEOSERVER_URL}/st_server_api/service/niktile/?x={x}&y={y}&z={z}&id=${item.id}&lyrname=${el.layerMeta.name}`,
            };
          }) || [],
      };
    });
  }
};

//图层选择
const handleChange = (e) => {
  let target = layerList.value.find((el) => el.id == e);

  if (target) {
    let map = GET_MAPBOX_MAP();

    targetData.value = target;

    let source = map.getSource('cuttingVectorSource');

    if (source) {
      map.removeSource('cuttingVectorSource');
      map.removeLayer('cuttingVectorLayer');
    }

    nextTick(() => {
      map.addSource('cuttingVectorSource', {
        type: 'raster', // 类型（必填）
        tiles: [
          // 用于指定一个或多个切片数据源的请求地址（可选，和 TileJSON 中的 tiles 属性一致）
          target.url,
        ],
        minzoom: 0, // 最小层级（可选，默认值为 0）
        maxzoom: 22, // 最大层级（可选，默认值为 22）
        attribution: '', // 属性信息（可选，用于地图展示时给用户看的一些信息）
      });
      map.addLayer({
        id: 'cuttingVectorLayer', // 唯一 id （必填）
        type: 'raster', // 类型（必填）
        // "metadata": { // 元数据（可选，用于为 layer 附加任意的属性。为避免冲突，建议添加前缀，如 mapbox:）
        //   "mapbox:name": "test"
        // },
        source: 'cuttingVectorSource', // 数据源的名称（除了 layer 的 type 为 background 外，source 必填）
        minzoom: 0, // 最小层级（可选，取值范围为 0 ~ 24。当 style 的 zoom 小于此 minzoom 时，layer 将被隐藏）
        maxzoom: 24, // 最大层级（可选，取值范围为 0 ~ 24。当 style 的 zoom 大于此 maxzoom 时，layer 将被隐藏）
        layout: {
          // 布局类属性
          visibility: 'visible', // 可见性（可选，可选值为 none、visible，默认值为 visible）
        },
      });

      const { min_x, min_y, max_x, max_y } = target.layerMeta.boundary_3857;
      let bbox = [
        [min_x, min_y],
        [max_x, max_y],
      ].map((item) => turf.toWgs84(turf.point(item)).geometry.coordinates);

      map.fitBounds(bbox, {
        padding: { top: 10, bottom: 25, left: 15, right: 15 },
      });
    });
  }
  // let map = null
};

// 文件手动上传
const handleUploadChange = (uploadFile) => {
  if (!UPLOAD_FILE_TYPE_ZIP(uploadFile.raw)) return ElMessage.warning('请上传zip文件');
  fileList.value = [uploadFile.raw];
};

// 关闭弹窗 并清理数据
const handleClose = () => {
  let map = GET_MAPBOX_MAP();

  if (!map) return;

  let source = map.getSource('cuttingVectorSource');

  if (source) {
    map.removeLayer('cuttingVectorLayer');
    map.removeSource('cuttingVectorSource');
  }

  emit('cuttingClose');
};

// 开始切割
const handleCutting = async () => {
  if (targetData.value && fileList.value.length) {
    loading.value = true;

    const [err, data] = await cuttingToShp({
      shp: fileList.value[0],
      serviceId: targetData.value.fid,
      layerName: targetData.value.label,
    });

    if (!err) {
      downloadBinaryFile(data.data, data.headers['content-type'], '数据切割');
    }

    loading.value = false;
  } else {
    ElMessage.warning('请先选择图层和上传文件');
  }
};

onMounted(() => {
  getRelationByIdApi();
});

onBeforeUnmount(() => {
  handleClose();
});
</script>
<template>
  <BorderBoxBg title="数据切割" class="cutting" @close="handleClose">
    <div class="cutting-box">
      <div class="item">
        <!-- <label>选择切割图层</label> -->
        <ElCascader
          v-model="layer"
          popper-class="cutting-pop bg-blue-400"
          class="pops"
          placeholder="选择切割图层"
          :options="mapImgList"
          :props="cascaderProps"
          @change="handleChange"
        />
      </div>
      <div class="item">
        <ElUpload
          :file-list="fileList"
          accept=".zip"
          :on-change="handleUploadChange"
          :auto-upload="false"
          @remove="() => (fileList = [])"
        >
          <div>
            <ElIcon class="el-icon--upload" size="40">
              <UploadFilled />
            </ElIcon>
            <div>点击上传文件</div>
          </div>
          <template #tip>
            <div class="el-upload__tip">请将完整shp文件打包成zip格式上传</div>
          </template>
        </ElUpload>
      </div>
      <div class="item">
        <ElButton :loading="loading" @click="handleCutting">开始切割</ElButton>
      </div>
    </div>
  </BorderBoxBg>
</template>

<style scoped lang="scss">
.cutting {
  bottom: 30px;

  .cutting-box {
    display: flex;
    flex-direction: column;
    gap: 20px;
    justify-content: center;
    padding-top: 20px;

    .item {
      text-align: center;

      :deep(.el-upload-list) {
        .el-upload-list__item-name,
        .el-icon {
          color: #fff;
        }

        .el-upload-list__item-name:hover,
        .el-icon:hover {
          color: #000;
        }
      }
    }

    .el-upload__tip {
      color: #eee;
    }
  }
}
</style>
<style lang="scss">
.el-cascader__dropdown.el-popper {
  li {
    color: #fff;
  }

  .el-cascader-node.in-active-path,
  .el-cascader-node.is-selectable.in-checked-path,
  .el-cascader-node.is-active {
    color: var(--el-cascader-menu-selected-text-color);
  }

  .el-cascader-node:not(.is-disabled):hover,
  .el-cascader-node:not(.is-disabled):focus {
    color: rgb(17, 222, 230);
  }
}

.el-cascader__dropdown.el-popper .el-popper__arrow::before {
  background-color: rgba(0, 69, 93, 1);
  border-color: rgba(0, 69, 93, 1);
}

.el-cascader-menu {
  border-right-color: rgba(0, 69, 93, 1);
}
</style>
